/**
 * 
 */
package com.itboye.ihomebank.net;

import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.json.JSONObject;

import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.text.Spanned;
import android.util.Log;
import android.util.TimeUtils;

import com.android.volley.DefaultRetryPolicy;
import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener;
import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.itboye.ihomebank.base.MyApplcation;
import com.itboye.ihomebank.constants.NetPublicConstant;
import com.itboye.ihomebank.util.ParamDeal;
import com.itboye.ihomebank.util.String2Spanned;
import com.itboye.ihomebank.util.TimesUtils;

/**
 * @author w
 * @param <T>
 * 
 */
public class ByJsonRequest<E> extends XJsonRequest<E> {

	ByJsonRequest(String url, XRequestListener<E> listener,
			XErrorListener errlistener) {
		super(url, listener, errlistener);
	}

	ByJsonRequest(int method, String url, XRequestListener<E> listener,
			XErrorListener errlistener) {
		super(method, url, listener, errlistener);

	}

	public static class Builder<T> {
		private ByJsonRequest<T> buildRequest;
		private String url = NetPublicConstant.URL;
		private XRequestListener<T> listener;
		private XErrorListener errlistener;
		private Type expectReturnType;
		private String typekey;
		private String apiVer;

		private Map<String, Object> map;
		private Map<String, Object> userParam;
		private String time = TimesUtils.getStamp();
		private String notify_id = TimesUtils.getStamp();
		private String desContent;

		/**
		 * 获取App的版本号
		 * 
		 * @return 返回App的版本号
		 */
		private String getVersionCode() {
			int appVersion = 0;
			try {

				PackageManager pm = MyApplcation.getInstance()
						.getPackageManager();
				PackageInfo info = pm.getPackageInfo(MyApplcation.getInstance()
						.getPackageName(), 0);
				appVersion = info.versionCode;
			} catch (Exception e) {

			}
			return "" + appVersion;
		}

		String appv = String.valueOf(getVersionCode());

		public Builder() {
			map = new HashMap<String, Object>();
			userParam = new HashMap<String, Object>();

			// 公共参数
			map.put(NetPublicParams.APP_VERSION, getVersionCode());
			map.put(NetPublicParams.APP_TYPE, "android");
			map.put(NetPublicParams.TIME, time);
			map.put(NetPublicParams.ALG, NetPublicParams.ALG_VALUE);
			map.put(NetPublicParams.NOTIFY_ID, time);
			map.put("client_id", NetPublicParams.CLIENT_ID);
			this.url = url + "?client_id=" + NetPublicParams.CLIENT_ID;
		}

		public Builder<T> addParams(Map<String, Object> params) {
			if (params != null) {
				Set<String> keys = params.keySet();
				Iterator<String> it = keys.iterator();
				while (it.hasNext()) {

					String key = it.next();
					Object obj = params.get(key);
					userParam.put(key, obj);
				}
			}
			return this;
		}

		public Builder<T> param(String k, String v) {
			userParam.put(k, v);
			return this;
		}

		/**
		 * 
		 * @param k
		 * @param v
		 * @return
		 */
		public Builder<T> param(String k, Object v) {
			userParam.put(k, v);
			return this;
		}

		public Builder<T> notifyID(String notify_id) {
			this.notify_id = notify_id;
			return this;
		}

		public Builder<T> url(String url) {
			this.url = url;
			return this;
		}

		public Builder<T> requestListener(XRequestListener<T> listener) {
			this.listener = listener;
			return this;
		}

		public Builder<T> errorListener(XErrorListener errlistener) {
			this.errlistener = errlistener;
			return this;
		}

		/**
		 * - 同时设置 type，ver，params
		 * 
		 * @param typekey
		 * @param ver
		 * @param params
		 * @return
		 */
		public Builder<T> setTypeVerParams(String typekey, String ver,
				Map<String, Object> params) {
			this.typekey = typekey;
			this.apiVer = ver;
			this.userParam = params;
			return this;
		}

		public Builder<T> setTypeVerParamsAndReturnClass(String typekey,
				String ver, Map<String, Object> params, Type expectReturnType) {
			this.typekey = typekey;
			this.apiVer = ver;
			this.userParam = params;
			this.expectReturnType = expectReturnType;
			return this;
		}

		public Builder<T> typeKey(String typekey) {
			this.typekey = typekey;
			return this;
		}

		public Builder<T> apiVer(String ver) {
			this.apiVer = ver;
			return this;
		}

		public Builder<T> requestMethod(int method) {
			return this;
		}

		public Builder<T> desEncode() {

			String param = new ParamDeal().dataEncrypt(userParam);
			String sign = signInfo(param);
			this.addParams(map).param(NetPublicParams.TYPE, typekey)
					.param(NetPublicParams.API_VER, apiVer)
					.param(NetPublicParams.DATA, param)
					.param(NetPublicParams.SIGN, sign);

			Gson gson = new GsonBuilder()
					.setFieldNamingPolicy(
							FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
					.registerTypeAdapter(Spanned.class, new String2Spanned())
					.create();

			String jsonStr = gson.toJson(this.userParam);

			Log.d("ByJsonRequest", jsonStr);
			this.desContent = DESUtil.encode(jsonStr,
					NetPublicParams.CLIENT_SECERET);
			Log.d("ByJsonRequest2", desContent);

			return this;
		}

		/**
		 * 设置返回数据类型
		 * 
		 * @param expectClass
		 * @return
		 */
		public Builder<T> setReturnDataType(Type expectReturnType) {
			this.expectReturnType = expectReturnType;
			return this;
		}

		/**
		 * 创建 MyJsonRequest对象
		 * 
		 * @return
		 */
		public ByJsonRequest<T> desEncodeThenBuildAndSend() {
			MyApplcation.addRequest(this.desEncode().build());
			return this.buildRequest;
		}

		/**
		 * 创建 MyJsonRequest对象
		 * 
		 * @return
		 */
		public ByJsonRequest<T> build() {
			if (listener == null) {
				System.err.println("XRequestListener == null !");
			}
			if (errlistener == null) {
				System.err.println("ErrorListener == null !");
			}

			if (null == typekey) {
				throw new RuntimeException(
						"typekey can not be null ! you should use typeKey(String typekey) ");
			}

			if (null == apiVer) {
				throw new RuntimeException(
						"apiVer can not be null ! you should use apiVer(String ver) ");
			}

			buildRequest = new ByJsonRequest<T>(url, listener, errlistener);
			buildRequest.setRetryPolicy(new DefaultRetryPolicy(10000,
					DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
					DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
			buildRequest.setExpectReturnType(expectReturnType);
			buildRequest.addParam(NetPublicParams.ITBOYE, desContent);
			buildRequest.setMethod(Method.POST);

			// 增加SocketLog调试
			buildRequest.addHeader("SocketLog",
					"SocketLog(tabid=2&client_id=slog_fc68e9)");
			return buildRequest;

		}

		private String signInfo(String userInf) {

			ParamDeal operate = new ParamDeal();
			String sign = operate.getMD5Sign(time, typekey, userInf,
					NetPublicParams.CLIENT_SECERET, notify_id);
			System.out.println("msg5" + sign);
			return sign;
		}

	}
}